/* ========================================================================= */
/* ------------------------------------------------------------------------- */
/*!		\file		PrpMdl.cc
		\date		june 2010
		\author		TNick

		\brief		Contains the implementation of PrpMdl class and related


	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	Please read ReadMe.txt and Licence.txt in root folder
	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


*/
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
//
//
//
//
/*  INCLUDES    ------------------------------------------------------------ */

#include "prpmdl.h"
#include "prptpl.h"

#include <QDebug>


/*  INCLUDES    ============================================================ */
//
//
//
//
/*  CLASS    --------------------------------------------------------------- */

/* ------------------------------------------------------------------------- */
PrpMdl::PrpMdl		(QObject *parent) :
		QAbstractItemModel(parent)
{
}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
PrpMdl::~PrpMdl		()
{

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
Qt::ItemFlags		PrpMdl::flags		( const QModelIndex & index ) const
{
	if (index.isValid())
		{
			PrpTpl* theItem = static_cast<PrpTpl*>(index.internalPointer());
			if (theItem == NULL)
				return Qt::NoItemFlags;

			if (index.column() == 1)
				{
					if (theItem->type() != PrpTpl::HEADER)
						return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable;
					else
						return Qt::ItemIsEnabled;
				}
			else
				return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
		}
	return Qt::NoItemFlags;

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QVariant				PrpMdl::headerData	(
		int section, Qt::Orientation orientation, int role ) const
{
	Q_UNUSED(orientation);

	if (role == Qt::DisplayRole)
		{
			if (section == 0)
				{
					return tr("Name");
				}
			else
				{
					return tr("Value");
				}
		}
	return QVariant();
}
/* ========================================================================= */


/* ------------------------------------------------------------------------- */
QVariant				PrpMdl::data		(
		const QModelIndex & midx, int role ) const
{

	qDebug() << "PrpMdl " << this << " asks for data on role" << role;

	/* check the validity of provided midx */
	if (midx.isValid() && (midx.row() >= 0) && (midx.column() >= 0))
		{ /* a valid index */

			PrpTpl*	pIt = static_cast<PrpTpl*>(midx.internalPointer());
			qDebug() << "  a valid index hosting item " << pIt ;

			/* be shure we have a valid item */
			if (pIt == NULL)
				return QVariant();
			if (pIt->row() == -1)
			{
					int ab = 1;
					ab = pIt->row();
			}
			qDebug() << "  we have a valid item: " << pIt << " at row " << pIt->row();


			int i = midx.column();
			if (i == 0)
				{ /* first column has the name */
					if (role == Qt::DisplayRole)
						{
							return pIt->name();
						}
					return QVariant();
				}
			else if (i == 1)
				{
					switch	(role)	{
					case	Qt::EditRole:
					case	Qt::DisplayRole:	{
									return pIt->valAsText();
								}
					case	Qt::DecorationRole:	{
									return pIt->valAsDecor();
								}
					case	Qt::ToolTipRole:
					case	Qt::StatusTipRole:	{
									return pIt->description();
								}
					default:					{
								return QVariant();
							}
					};
				}

			/* other roles are not handled */
			return QVariant();
		}
	else
		{
			qDebug() << "  an invalid index";
			return QVariant();
		}


	return QVariant();


}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
int						PrpMdl::rowCount	( const QModelIndex & midx) const
{

	qDebug() << "PrpMdl " << this << " req rowCount";

	/* for invalid input */
	if (!midx.isValid())
		{ /* return the number of top level items */
			PrpMdl* pt = (PrpMdl*)this;
			qDebug() << "  request for top level returns " << pt->count() << " items";
			return pt->count();
		}
	PrpNode *theNode; PrpTpl *theItem;


	theItem = static_cast<PrpTpl*>(midx.internalPointer());
	qDebug() << "  request for leaf " << theItem;
	if (theItem != NULL)
		{
			if (theItem->isAbleToHost())
				{
					theNode = static_cast<PrpNode*>(theItem);
					qDebug() << "  found a node item with " <<
							theNode->count() << " items";
					return theNode->count();
				}
			qDebug() << "  is not able to host (dead end)";
		}
	return 0;

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QModelIndex PrpMdl::index(int a_row, int a_column, const QModelIndex &parent) const
{
	PrpNode *		parentItem;
	PrpNode *		theItem;

	qDebug() << "PrpMdl " << this << " req index for row "
			<< a_row << " and column " << a_column;
	if ((a_row < 0) || (a_column < 0))
		{
			qDebug() << "  weird location";
			return QModelIndex();
		}
	/* diferentiate between root and leaf items */
	if (parent.isValid())
		{	/* this is a leaf */

			parentItem = static_cast<PrpNode*>(parent.internalPointer());
			theItem = static_cast<PrpNode*>(parentItem->item(a_row));
			qDebug() << "  an valid parent " << parentItem << " => leaf: " << theItem;
			if (theItem == NULL)
				return QModelIndex();
			return createIndex(a_row, a_column, theItem);
		}
	else
		{	/* this is a root item */

			PrpMdl* pEM = (PrpMdl*)this;
			theItem = (PrpNode*)pEM->hd.item(a_row);
			qDebug() << "  an invalid parent => top level item " << theItem;
			if (theItem == NULL)
				return QModelIndex();
			return createIndex(a_row, a_column, theItem);
		}

	return QModelIndex();

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
QModelIndex PrpMdl::parent(const QModelIndex &midx) const
{

	qDebug() << "PrpMdl " << this << " req parent";

	/* if invalid, discard */
	if (!midx.isValid())
		{
			qDebug() << "  invalid";
			return QModelIndex();
		}


	/* get associated item */
	PrpTpl *theItem = static_cast<PrpTpl*>(midx.internalPointer());
	if (theItem == NULL)
		{
			qDebug() << "  no associated item";
			return QModelIndex();
		}
	qDebug() << "  associated item is " << theItem;


	/* top level items have no father */
	if (theItem->isTopLevel())
		{
			qDebug() << "  top level => no parent";
			return QModelIndex();
		}
	else
		{ /* but leafs have */
			PrpNode *parentItem = theItem->parent();
			qDebug() << "  not top level => parent is " << parentItem;
			if (parentItem == NULL)
				{
					/* this case should have been filtered out */
					Q_ASSERT(0);
					return QModelIndex();
				}
			return createIndex(parentItem->row(),0,parentItem);
		}

	return QModelIndex();

}
/* ========================================================================= */

/* ------------------------------------------------------------------------- */
bool PrpMdl::setData(const QModelIndex &midx, const QVariant &value,
					 int role)
{

	if (role == Qt::EditRole)
		{
			/* check the validity of provided midx */
			if (midx.isValid())
				{ /* a valid index */
					if (midx.column() == 1)
						{ /* only column 1 has editable data */
							PrpTpl*	pIt = static_cast<PrpTpl*>(midx.internalPointer());
							if (pIt != NULL)
								{ /* a valid item */
									if (pIt->changeVal(value) == true)
										{ /* the item accepted the change */
											emit dataChanged(midx, midx);
											return true;
										}
								}
						}
				}
		}

	return false;
}
/* ========================================================================= */

/*  CLASS    =============================================================== */
//
//
//
/* ------------------------------------------------------------------------- */
/* ========================================================================= */
